#ifndef GTL_CPP_UTILS_HEADER_GUARD
#define GTL_CPP_UTILS_HEADER_GUARD

#ifndef __APPLE__
#include "external/pstdint.h"
#else
#include <stdint.h>
#endif
#include "gtlDebug.h"

/// TODO: Coroutines
/// http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
/// http://www.codeproject.com/KB/cpp/cpp_generators.aspx

/// TODO: Damn, I made a stupid C++ macro for foreach:
/*
template <typename T>
struct Iterator
{
  virtual T start() = 0;
  virtual bool isok() = 0;
  virtual T next() = 0;
};

struct range : public Iterator<int>
{
  int value;
  int maxvalue;

  range(int v) : value(0), maxvalue(v) {}
  virtual int start() { return value; }
  virtual bool isok() { return value < maxvalue; }
  virtual int next() { return ++value; }
};

#define foreach(type, itvar, iterator) Iterator<type>& __it__##__LINE__ = iterator; for (type itvar = __it__##__LINE__.start(); __it__##__LINE__.isok(); itvar = __it__##__LINE__.next())

foreach (int, i, range(10))
{
}
*/

namespace GTL
{
  namespace Utilities
  {
    #define GTL_ZERO_THIS___DESTROYS_VTABLE memset( this, 0, sizeof( *this ) );

    #ifdef  GTL_64_BIT_COMPILER
    #define GTL_OFFSET_OF_MEMBER(s,m)   (uint32_t)( (ptrdiff_t)&reinterpret_cast<const volatile char&>((((s *)0)->m)) )
    #else
    #define GTL_OFFSET_OF_MEMBER(s,m)   (uint32_t)&reinterpret_cast<const volatile char&>((((s *)0)->m))
    #endif

    ///************************************************************************/
    ///* Miscellaneous                                                        */
    ///************************************************************************/
  
    /// Class: Flags
    /// Holds 32 binary flags
    class Flags
    {
      uint32_t value;
    public:
      Flags() { value = 0; }
      Flags(const Flags& other) : value(other.value) { }
      Flags(uint32_t val) : value(val) { }
      inline Flags& operator=(const Flags& other) { value = other.value; return *this; }
      inline Flags& operator=(uint32_t val) { value = val; return *this; }
      inline void Clear() { value = 0; }
      inline void SetValue(uint32_t val) { value = val; }
      inline void Set(int flag) { value |= 1<<flag; }
      inline void Unset(int flag) { value &= ~(1<<flag); }
      inline void Toggle(int flag) { value ^= (1<<flag); }
      inline bool Get(int flag) const { return (value & (1<<flag))!=0; }
      inline uint32_t GetValue() const { return value; }
      inline operator uint32_t() const { return value; }
    };

		#define GTL_FLAGS(name) enum __gtl_flags_##name; \
			uint64_t __flags_var_##name; \
			inline bool HasFlag(__gtl_flags_##name flag) const { return !!(__flags_var_##name & (1LL<<flag)); } \
			inline void SetFlag(__gtl_flags_##name flag) { __flags_var_##name |= (1LL<<flag); } \
			inline void UnsetFlag(__gtl_flags_##name flag) { __flags_var_##name &= ~(1LL<<flag); } \
			inline void ToggleFlag(__gtl_flags_##name flag) { __flags_var_##name ^= (1LL<<flag); } \
			inline uint64_t Get##name##FlagsValue() const { return __flags_var_##name; } \
			inline void Set##name##FlagsValue(uint64_t val) { __flags_var_##name = val; } \
			enum __gtl_flags_##name

    template <typename T>
    class Slice
    {
    public:
      Slice() { ptr = 0; size = 0; }
      template <size_t SIZE>
      Slice(T(& obj)[SIZE]) { ptr = &obj[0]; size = SIZE; }
      template <size_t SIZE>
      Slice(T(& obj)[SIZE], size_t from, size_t to) { GTL_ASSERT(from < SIZE && to < SIZE); ptr = &obj[from]; size = to-from; }
      Slice(T* obj, size_t s) { ptr = obj; size = s; }

      T& operator[](size_t index) { GTL_ASSERT(index < size); return ptr[index]; }
      const T& operator[](size_t index) const { GTL_ASSERT(index < size); return ptr[index]; }

      size_t GetSize() const { return size; }

      static Slice<T> Create(size_t size) { return Slice(new T[size], size); }
      void Destroy() { delete[] ptr; }
    private:
      T* ptr;
      size_t size;
    };

    template <typename T>
    class Slice2D
    {
    public:
      Slice2D() { ptr = 0; width = height = 0; }
      template <size_t WIDTH, size_t HEIGHT>
      Slice2D(T(& obj)[WIDTH][HEIGHT]) { ptr = &obj[0]; width = WIDTH; height = HEIGHT; }
      Slice2D(T** obj, size_t w, size_t h) { ptr = obj; width = w; height = h; }

      Slice<T> operator[](size_t index) { GTL_ASSERT(index < width); return Slice<T>(ptr[index], width); }
      const Slice<T>& operator[](size_t index) const { GTL_ASSERT(index < width); return Slice<T>(ptr[index], width); }

      size_t GetWidth() const { return width; }
      size_t GetHeight() const { return height; }

      static Slice2D<T> Create(size_t w, size_t h)
      {
        T** ptr = new T*[w];
        for (size_t i=0; i<h; i++) ptr[i] = new T[h];
        return Slice2D(ptr, w, h);
      }
      void Destroy() { for (size_t i=0; i<width; i++) this->operator [](i).Destroy(); delete[] ptr; }
    private:
      T** ptr;
      size_t width, height;
    };

    ///************************************************************************/
    ///* Scope deferring                                                      */
    ///************************************************************************/

    typedef void*(*DeferedFunction)(void*);

    template <typename T>
    class ScopeDeferFunctionCall
    {
    public:
      ScopeDeferFunctionCall(const T& arg, DeferedFunction func)
        : mArgument(arg), mFunction(func), mWillFire(true)
      {
      }
      void Fire(bool fireAgain = false)
      {
        if (!mWillFire) return;

        mFunction(mArgument);
        mWillFire = fireAgain;
      }
      ~ScopeDeferFunctionCall()
      {
        Fire();
      }
    private:
      ScopeDeferFunctionCall() {}
      bool mWillFire;
      T mArgument;
      DeferedFunction mFunction;
    };

    #define GTL_SCOPE_DEFER_FUNCTION_CALL(type, argument, function) \
      GTL::Utilities::ScopeDeferFunctionCall< type > __GTL_ScopeDeferFunctionCallObject_##GTL_COUNTER##__( obj , \
        (DeferedFunction) & function);

    template <typename T>
    class ScopeDeferMethodCall
    {
    public:
      typedef void*(T::*MethodType)();

      ScopeDeferMethodCall(T& object, MethodType func)
        : mObject(object), mFunction(func), mWillFire(true)
      {
      }
      void Fire(bool fireAgain = false)
      {
        if (!mWillFire) return;

        ((mObject).*(mFunction))();
        mWillFire = fireAgain;
      }
      ~ScopeDeferMethodCall()
      {
        Fire();
      }
    private:
      ScopeDeferMethodCall() {}
      bool mWillFire;
      MethodType mFunction;
      T& mObject;
    };

    #define GTL_SCOPE_DEFER_METHOD_CALL(type, obj, method) \
      GTL::Utilities::ScopeDeferMethodCall< type > __GTL_ScopeDeferMethodCallObject_##GTL_COUNTER##__( obj , \
        (GTL::Utilities::ScopeDeferMethodCall< type >::MethodType) & type :: method);

    template <typename T>
    class ScopeDeferDelete
    {
    public:
      ScopeDeferDelete(T* object)
        : mObject(object)
      {
      }
			T* Release()
			{
				T* temp = mObject;
				mObject = 0;
				return temp;
			}
      void Fire()
      {
        delete mObject;
        mObject = 0;
      }
      ~ScopeDeferDelete()
      {
        Fire();
      }
			operator T*()
			{
				return mObject;
			}
    private:
      ScopeDeferDelete() {}
      T* mObject;
    };

    #define GTL_SCOPE_DEFER_DELETE(type, obj) \
      GTL::Utilities::ScopeDeferDelete< type > __GTL_ScopeDeferDeleteObject_##GTL_COUNTER##__( obj );

    template <typename T>
    class ScopeDeferDeleteArray
    {
    public:
      ScopeDeferDeleteArray(T* array)
        : mArray(array)
      {
      }
			T* Release()
			{
				T* temp = mArray;
				mArray = 0;
				return temp;
			}
      void Fire()
      {
        delete[] mArray;
        mArray = 0;
      }
      ~ScopeDeferDeleteArray()
      {
        Fire();
      }
    private:
      ScopeDeferDeleteArray() {}
      T* mArray;
    };

    #define GTL_SCOPE_DEFER_DELETE_ARRAY(type, obj) \
      GTL::Utilities::ScopeDeferDeleteArray< type > __GTL_ScopeDeferDeleteArrayObject_##GTL_COUNTER##__( obj );

    ///************************************************************************/
    ///* Reference counted pointers                                           */
    ///************************************************************************/

    /// TODO: FIXME: these are not thread safe! (yet)

		/// TODO: FIXME: I SUCK! Make this the same as the smart pointer
    template <typename T>
    class ReferenceCountedSmartArray
    {
    protected:
      class ReferenceCounter
      {
      public:
        void AddRef() { mCount++; }
        int Release() { return --mCount; }
      protected:
        int mCount;
      };
    public:
      ReferenceCountedSmartArray() : mPointer(0), mReferenceCounter(0) 
      {
        mReferenceCounter = new ReferenceCounter();
        mReferenceCounter->AddRef();
      }
      ReferenceCountedSmartArray(T* pValue) : mPointer(pValue), mReferenceCounter(0)
      {
        mReferenceCounter = new ReferenceCounter();
        mReferenceCounter->AddRef();
      }
      ReferenceCountedSmartArray(const ReferenceCountedSmartArray<T>& sp) : mPointer(sp.mPointer), mReferenceCounter(sp.mReferenceCounter)
      {
        mReferenceCounter->AddRef();
      }
      ~ReferenceCountedSmartArray()
      {
        if(mReferenceCounter->Release() == 0)
        {
          delete[] mPointer;
          delete mReferenceCounter;
        }
      }

      T& operator[] (size_t index) const { return mPointer[index]; }

      T* Get() const { return mPointer; }

      bool IsUnique() const { return mReferenceCounter->mCount == 1; }
      int GetUseCount() const { return mReferenceCounter->mCount; }

      ReferenceCountedSmartArray<T>& operator = (const ReferenceCountedSmartArray<T>& sp)
      {
        if (this != &sp)
        {
          if(mReferenceCounter->Release() == 0)
          {
            delete[] mPointer;
            delete mReferenceCounter;
          }
          mPointer = sp.mPointer;
          mReferenceCounter = sp.mReferenceCounter;
          mReferenceCounter->AddRef();
        }
        return *this;
      }

      bool operator==(const ReferenceCountedSmartArray<T>& sp) { return mPointer == sp->pData; }
      bool operator!=(const ReferenceCountedSmartArray<T>& sp) { return mPointer != sp->pData; }

      bool operator==(const T* sp) { return mPointer == sp; }
      bool operator!=(const T* sp) { return mPointer != sp; }
    protected:
      T* mPointer;       // pointer
      ReferenceCounter* mReferenceCounter; // Reference count
    };

    template <typename T>
    struct RegularDeletePointer
    {
      void operator() (T* ptr)
      {
        delete ptr;
      }
    };

    template <typename T, typename D = RegularDeletePointer<T> >
    class ReferenceCountedSmartPointer
    {
    protected:
      class ReferenceCounter
      {
      public:
        ReferenceCounter() : mCount(0) { }
        void AddRef() { mCount++; }
        int Release() { return --mCount; }
        inline int GetCount() const { return mCount; }
      protected:
        int mCount;
      };
    public:
      ReferenceCountedSmartPointer() : mPointer(0), mReferenceCounter(0), mDestructor(D())
      {
        //mReferenceCounter = new ReferenceCounter();
        //mReferenceCounter->AddRef();
      }
      ReferenceCountedSmartPointer(T* pValue) : 
        mPointer(pValue), mReferenceCounter(new ReferenceCounter), mDestructor(D())
      {
        //mReferenceCounter = new ReferenceCounter();
        mReferenceCounter->AddRef();
      }
      ReferenceCountedSmartPointer(T* pValue, D destructor) : 
        mPointer(pValue), mReferenceCounter(new ReferenceCounter), mDestructor(destructor)
      {
        //mReferenceCounter = new ReferenceCounter();
        mReferenceCounter->AddRef();
      }
      ReferenceCountedSmartPointer(const ReferenceCountedSmartPointer<T,D>& sp) : mPointer(sp.mPointer), mReferenceCounter(sp.mReferenceCounter), mDestructor(sp.mDestructor)
      {
				if (mReferenceCounter)
					mReferenceCounter->AddRef();
      }
      ~ReferenceCountedSmartPointer()
      {
        if (mReferenceCounter && mReferenceCounter->Release() == 0)
        {
          //delete mPointer;
          mDestructor(mPointer);
          delete mReferenceCounter;
        }
      }

      T& operator* () const { return *mPointer; }
      T* operator-> () const { return mPointer; }
      T* Get() const { return mPointer; }
#ifdef GTL_IS_CPP_0X
      explicit operator T* () const { return mPointer; }
#endif
			operator bool () const { return !!mPointer; }

      bool IsUnique() const { return mReferenceCounter && mReferenceCounter->GetCount() == 1; }
      int GetUseCount() const { return mReferenceCounter ? mReferenceCounter->GetCount() : 0; }

      ReferenceCountedSmartPointer<T,D>& operator = (const ReferenceCountedSmartPointer<T,D>& sp)
      {
        if (this != &sp)
        {
          if (mReferenceCounter && mReferenceCounter->Release() == 0)
          {
            //delete mPointer;
            mDestructor(mPointer);
            delete mReferenceCounter;
          }
          mPointer = sp.mPointer;
          mReferenceCounter = sp.mReferenceCounter;
          mDestructor = sp.mDestructor;
          mReferenceCounter->AddRef();
        }
        return *this;
      }

      ReferenceCountedSmartPointer<T,D>& operator = (T* ptr)
      {
        if (mPointer != ptr)
        {
          if (mReferenceCounter && mReferenceCounter->Release() == 0)
          {
            //delete mPointer;
            mDestructor(mPointer);
            delete mReferenceCounter;
            mReferenceCounter = 0;
          }
          mPointer = ptr;
          if (ptr)
          {
            mReferenceCounter = new ReferenceCounter();
            mReferenceCounter->AddRef();
          }
        }
        return *this;
      }

      /*
      /// TODO: Check if this is really needed
      ReferenceCountedSmartPointer<T,D>& operator = (int i)
      {
        if (i == 0)
        {
          return operator=((T*)i);
        }
        return *this;
      }
      */

      bool operator==(const ReferenceCountedSmartPointer<T,D>& sp) const { return mPointer == sp.mPointer; }
      bool operator!=(const ReferenceCountedSmartPointer<T,D>& sp) const { return mPointer != sp.mPointer; }

      bool operator==(const T* sp) const { return mPointer == sp; }
      bool operator!=(const T* sp) const { return mPointer != sp; }

      bool operator>(const T* sp) const { return mPointer > sp; }
      bool operator<(const T* sp) const { return mPointer < sp; }

      bool operator<(const ReferenceCountedSmartPointer<T,D>& sp) const { return mPointer < sp.mPointer; }
      bool operator>(const ReferenceCountedSmartPointer<T,D>& sp) const { return mPointer > sp.mPointer; }
    protected:
      T* mPointer;       // pointer
      ReferenceCounter* mReferenceCounter; // Reference count
      D mDestructor;
    };

		template <typename T, typename D = RegularDeletePointer<T> >
    class AutoPointer
    {
    public:
      AutoPointer() : mPointer(0)
      {
      }
      AutoPointer(T* pValue) : 
        mPointer(pValue)
      {

      }
      ~AutoPointer()
      {
				D dest;
				dest(mPointer);
			}

      T& operator* () const { return *mPointer; }
      T* operator-> () const { return mPointer; }
      T* Get() const { return mPointer; }
			operator bool () const { return !!mPointer; }

      AutoPointer<T,D>& operator = (T* ptr)
      {
        if (mPointer != ptr)
        {
          D dest;
					dest(mPointer);

          mPointer = ptr;
        }
        return *this;
      }

      bool operator==(const AutoPointer<T,D>& sp) const { return mPointer == sp.mPointer; }
      bool operator!=(const AutoPointer<T,D>& sp) const { return mPointer != sp.mPointer; }

      bool operator==(const T* sp) const { return mPointer == sp; }
      bool operator!=(const T* sp) const { return mPointer != sp; }

      bool operator>(const T* sp) const { return mPointer > sp; }
      bool operator<(const T* sp) const { return mPointer < sp; }

      bool operator<(const AutoPointer<T,D>& sp) const { return mPointer < sp.mPointer; }
      bool operator>(const AutoPointer<T,D>& sp) const { return mPointer > sp.mPointer; }
    protected:
      T* mPointer;
		private:
			AutoPointer<T,D>& operator = (const AutoPointer<T,D>& sp)
			{
				return *this;
			}
    };
  }
}

#endif